<template>
  <view class="anchor flex-col" :class="customClass">
    <view
      class="anchor-tabs tabs-sticky"
      :style="{ top: $u.addUnit(stickyTop, 'rpx') }"
      :id="anchorId">
      <tabs-el
        :list="tabs"
        :current="tabIndex"
        keyName="label"
        lineWidth="60rpx"
        lineHeight="8rpx"
        :activeStyle="{ color: '#4374FF' }"
        :inactiveStyle="{ color: '#666' }"
        :evenly="evenly"
        @change="handleTabsChange" />
    </view>
    <view class="anchor-warp padding-24">
      <view
        v-for="item in tabs"
        :key="item.name"
        :class="[item.sClass, anchorClass]"
        :id="item.name">
        <slot :name="item.name" />
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: "Anchor",
  // #ifdef MP-WEIXIN
  options: { virtualHost: true },
  // #endif
  props: {
    scrollTop: { type: Number, default: 0 },
    stickyTop: {
      type: [String, Number],
      default: 0,
    }, //锚点导航距离顶部距离
    evenly: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    const id = uni.$u.guid(6);
    return {
      tabs: [],
      tabIndex: -1,
      anchorId: id,
      anchorClass: "anchor-" + id,
    };
  },
  mounted() {
    this.initTabs();
    setTimeout(() => {
      this.observer = uni.createIntersectionObserver(this, {
        observeAll: true,
      });
      const $anchor = {};
      const changeAnchor = () => {
        const value = Object.values($anchor);
        let length = value.length;
        while (length--) {
          if (value[length]) return (this.tabIndex = length);
        }
      };
      this.observer
        .relativeToViewport()
        .observe("." + this.anchorClass, res => {
          if (this.isClickTab) return;
          if (res.intersectionRatio > 0) {
            $anchor[res.id] = true;
          } else {
            $anchor[res.id] = false;
          }
          changeAnchor();
        });
    }, 300);
  },
  destroyed() {
    if (this.observer) this.observer.disconnect();
  },
  methods: {
    initTabs() {
      const tabs = [];
      const children = this.$children;
      for (const index in children) {
        const item = children[index];
        if (item.$options.name === "TabsPane") {
          let { name, label, sClass } = item;
          name = name ?? index;
          label = label ?? name;
          tabs.push({ label, name, sClass });
        }
      } //读取TabsPane数据
      this.tabs = tabs;
    },
    async handleTabsChange(item) {
      this.isClickTab = true;
      clearTimeout(this.timer);
      this.tabIndex = item.index;
      this.$emit("change", item);
      if (!this.anchorTabHeight) {
        //获取锚点导航高度
        await this.$uGetRect("#" + this.anchorId).then(res => {
          this.anchorTabHeight = res.height;
        });
      }
      const { top } = await this.$uGetRect("#" + item.name);
      uni.pageScrollTo({
        scrollTop: this.scrollTop + top - this.anchorTabHeight,
      });
      this.timer = setTimeout(() => (this.isClickTab = false), 300);
    },
  },
};
</script>
<style>
.tabs-sticky {
  position: sticky;
  top: 0;
  z-index: 2023;
}
</style>
